package com.simple.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.simple.common.constant.SystemRedisConstans;
import com.simple.common.exception.ServiceException;
import com.simple.framework.constant.HttpStatus;
import com.simple.framework.core.auth.JwtContext;
import com.simple.framework.core.redis.RedisService;
import com.simple.framework.utils.BeanCopyUtils;
import com.simple.system.domain.dto.AddSysDeptDto;
import com.simple.system.domain.entity.SysDept;
import com.simple.system.domain.vo.SysDeptDetailsVo;
import com.simple.system.domain.vo.SysListDeptVo;
import com.simple.system.mapper.SysDeptMapper;
import com.simple.system.service.SysDeptService;
import com.simple.system.service.SysUserService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * @Description 部门表(SysDept)表服务实现类
 * @Author xiaoke
 * @Date 2024/8/10 18:00
 * @Version 1.0
 */
@Service("sysDeptService")
public class SysDeptServiceImpl implements SysDeptService {

    private final SysDeptMapper sysDeptMapper;

    private final RedisService redisService;

    private final SysUserService sysUserService;

    public SysDeptServiceImpl(SysDeptMapper sysDeptMapper, RedisService redisService, SysUserService sysUserService) {
        this.sysDeptMapper = sysDeptMapper;
        this.redisService = redisService;
        this.sysUserService = sysUserService;
    }

    @Override
    public List<SysListDeptVo> listDeptTree() {
        List<SysListDeptVo> deptTree = redisService.getCacheList(SystemRedisConstans.SYS_DEPT);
        if (deptTree != null && !deptTree.isEmpty()) {
            return deptTree;
        }

        List<SysDept> sysDepts = sysDeptMapper.selectList(null);
        deptTree = getDeptTree(0L,BeanCopyUtils.copyBeanList(sysDepts, SysListDeptVo.class));
        redisService.setCacheList(SystemRedisConstans.SYS_DEPT, deptTree);
        return deptTree;
    }

    @Override
    public SysDeptDetailsVo get(Long id) {
        String key = SystemRedisConstans.SYS_DEPT_DETAILS + id;
        if (redisService.hasKey(key)) {
            return redisService.getCacheObject(key);
        }
        SysDeptDetailsVo sysDept = sysDeptMapper.selectByIdDetails(id);
        if (sysDept == null) {
            throw new ServiceException("该部门不存在", HttpStatus.BAD_REQUEST);
        }
        redisService.setCacheObject(key, sysDept);
        return sysDept;
    }

    @Transactional
    @Override
    public Long create(AddSysDeptDto dto) {
        LambdaQueryWrapper<SysDept> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysDept::getDeptName, dto.getDeptName());
        if (sysDeptMapper.selectCount(queryWrapper) > 0) {
            throw new ServiceException("该部门已存在", HttpStatus.BAD_REQUEST);
        }
        commonCheck(dto);
        // TODO 检查负责人是否存在
        SysDept sysDept = new SysDept();
        BeanUtils.copyProperties(dto, sysDept);

        sysDeptMapper.insert(sysDept);
        sysDeptMapper.insertDeptLeaders(sysDept.getId(), dto.getLeaderIds());
        redisService.deleteObject(SystemRedisConstans.SYS_DEPT);
        return sysDept.getId();
    }

    @Transactional
    @Override
    public void update(Long id, AddSysDeptDto dto) {
        SysDept sysDept = sysDeptMapper.selectById(id);
        if (sysDept == null) {
            throw new ServiceException("该部门不存在", HttpStatus.BAD_REQUEST);
        }
        SysDept tmpDept = sysDeptMapper.existDeptName(dto.getDeptName());
        if (tmpDept != null && !tmpDept.getId().equals(sysDept.getId())) {
            throw new ServiceException("该部门名不可用", HttpStatus.BAD_REQUEST);
        }
        commonCheck(dto);
        BeanUtils.copyProperties(dto, sysDept);
        //删除部门负责人
        sysDeptMapper.deleteDeptLeaders(id);
        //
        if(!dto.getLeaderIds().isEmpty()){
            sysDeptMapper.insertDeptLeaders(id, dto.getLeaderIds());
        }
        sysDept.setUpdateTime(LocalDateTime.now());
        //设置更新者Id
        sysDept.setUpdateId(JwtContext.getUserId());
        sysDeptMapper.updateById(sysDept);
        redisService.deleteObject(SystemRedisConstans.SYS_DEPT);
        redisService.deleteObject(SystemRedisConstans.SYS_DEPT_DETAILS + sysDept.getId());
    }

    @Transactional
    @Override
    public void delete(Long id) {
        if (sysUserService.checkDeptByUser(id)) {
            throw new ServiceException("该部门下有用户，不能删除");
        }
        sysDeptMapper.deleteById(id);
        redisService.deleteObject(SystemRedisConstans.SYS_DEPT);
    }

    /**
     * 递归获取部门树
     * @param pid 父id
     * @param depts 部门列表
     * @return List<SysMenu>
     */
    private List<SysListDeptVo> getDeptTree(Long pid, List<SysListDeptVo> depts) {
        List<SysListDeptVo> children = new ArrayList<>();
        for (SysListDeptVo dept : depts) {
            if (dept.getPid().equals(pid)) {
                children.add(dept);
                // 递归调用，获取子菜单的子菜单
                dept.setChildren(getDeptTree(dept.getId(), depts));
            }
        }
        return children;
    }

    /**
     * 校验
     *
     * @param dto 参数
     */
    private void commonCheck(AddSysDeptDto dto) {
        if (dto.getLeaderIds().isEmpty()) {
            throw new ServiceException("部门不能没有负责人", HttpStatus.BAD_REQUEST);
        }
        if (dto.getPid() != null && dto.getPid() != 0) {
            if (sysDeptMapper.selectById(dto.getPid()) == null) {
                throw new ServiceException("父级部门不存在", HttpStatus.BAD_REQUEST);
            }
        }
    }
}

